#include "client.h"
#include "ui_client.h"

#include "index.h"
#include <QFile>
#include <QtDebug>
#include <QMessageBox>
#include <QHostAddress>

Client::Client(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Client)
{
    ui->setupUi(this);
    m_prh = new ResHandler;

    //加载配置
    loadConfig();
    //关联连接信号与槽函数
    connect(&m_tcpSocket,&QTcpSocket::connected, this, &Client::showConnect);
    connect(&m_tcpSocket,&QTcpSocket::readyRead, this, &Client::recvMsg);
    //连接服务器
    m_tcpSocket.connectToHost(QHostAddress(m_strIP), m_usPort);
}

Client::~Client()
{
    delete ui;
    delete m_prh;
}

void Client::loadConfig()
{
    QFile file(":/client.config");//文件路径，固定冒号开头
    if(file.open(QIODevice::ReadOnly)) {//打开文件，只读
    QByteArray baData = file.readAll();

    QString strData = QString(baData);//存下来
    QStringList strList = strData.split("\r\n");//按\r\n拆分
    m_strIP = strList.at(0);//设置为类的成员变量
    m_usPort = strList.at(1).toShort();//设置为类的成员变量
    qDebug() << "loadConfig ip:"<< m_strIP <<"port:"<< m_usPort;//防止找不到是哪个函数的，在打印的时候加上名
    file.close();//关闭文件
    }
    else {
        QMessageBox::warning(this,"open config", "open config failed");//或者打开失败
    }
}

Client &Client::getInstance()
{
    //单例
    static Client instance;
    return instance;
}

void Client::recvMsg()
{
    qDebug() << "readPDU 接收消息长度" << m_tcpSocket.bytesAvailable();

    QByteArray data = m_tcpSocket.readAll();
    buffer.append(data);
    while(buffer.size() >= int(sizeof(PDU))){//判断是否有一个完整的PDU结构体
        PDU* pdu = (PDU*)buffer.data();//转换为pdu类型的指针
        if(buffer.size() < int(pdu->uiPDULen)){//总的pdu协议长度和buffer比较
            break;//不够一个包
        }
        handlePDU(pdu);//处理
        buffer.remove(0,pdu->uiPDULen);//buffer清除处理完的pdu
    }
}

void Client::handlePDU(PDU *pdu)
{
    qDebug() <<"\n\n\nrecvMsg 消息类型：" <<pdu->uiMsgType
             <<"消息内容：" <<pdu->caMsg
             <<"参数内容：" <<pdu->caData;

    switch (pdu->uiMsgType) {
    case ENUM_MSG_TYPE_REGIST_RESPOND: {
        m_prh->handleRegist(pdu);
        break;
    }
    case ENUM_MSG_TYPE_LOGIN_RESPOND: {
       m_prh->handleLogin(pdu);
        break;
    }
    case ENUM_MSG_TYPE_FIND_USER_RESPOND: {
        m_prh->handleFindUser(pdu);
        break;
    }
    case ENUM_MSG_TYPE_ONLINE_USER_RESPOND: {
        m_prh->handleOnlineUser(pdu, m_strLoginName);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_RESPOND: {
        m_prh->handleADDFriend(pdu);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST: {
        m_prh->handleADDFriendRequest(pdu);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_AGREE_RESPOND: {
        m_prh->handleADDFriendAgree();
        break;
    }
    case ENUM_MSG_TYPE_ONLINE_FRIEND_RESPOND: {
        m_prh->handleOnlineFriend(pdu);
        break;
    }
    case ENUM_MSG_TYPE_DEL_FRIEND_RESPOND: {
        m_prh->handleDelFriend(pdu);
        break;
    }
    case ENUM_MSG_TYPE_CHAT_REQUEST: {
        m_prh->handleChat(pdu);
        break;
    }
    case ENUM_MSG_TYPE_MKDIR_RESPOND: {
        m_prh->handlemkdir(pdu);
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_FILE_RESPOND: {
        m_prh->handleFlushFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_DEL_DIR_RESPOND: {
        m_prh->delDir(pdu);
        break;
    }
    case ENUM_MSG_TYPE_RENAME_FILE_RESPOND: {
        m_prh->RenameFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_DEL_FILE_RESPOND: {
        m_prh->delFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_MOVE_FILE_RESPOND: {
        m_prh->MoveFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_UPLOAD_FILE_RESPOND: {
        m_prh->UploadFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_UPLOAD_FILE_DATA_RESPOND: {
        m_prh->UploadFileData(pdu);
        break;
    }
    case ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND: {
        m_prh->DownloadFile(pdu);
        break;
    }
    case ENUM_MSG_TYPE_DOWNLOAD_FILE_DATA_RESPOND: {
        m_prh->DownloadFileData(pdu);
        break;
    }
    case ENUM_MSG_TYPE_SHARE_FILE_RESPOND: {
        m_prh->ShareFile();
        break;
    }
    case ENUM_MSG_TYPE_SHARE_FILE_REQUEST: {
        m_prh->ShareFileRequest(pdu);
        break;
    }
    case ENUM_MSG_TYPE_SHARE_FILE_AGREE_RESPOND: {
        m_prh->ShareFileAgree(pdu);
        break;
    }
    default:
        break;
    }
}

void Client::sendPDU(PDU *pdu)
{
    if(pdu == NULL)//判空
    {
        return;
    }
    m_tcpSocket.write((char*)pdu, pdu->uiPDULen);//用socket成员变量调用write
    free(pdu);
    pdu = NULL;
}

void Client::showConnect()
{
    QMessageBox::information(this,"连接服务器","连接服务器成功");
}

void Client::on_regist_PB_clicked()
{
    QString strName = ui->user_LE->text();
    QString strPwd = ui->pwd_LE->text();

    PDU* pdu = mkPDU(0);//括号里是柔性数组的长度
    pdu->uiMsgType = ENUM_MSG_TYPE_REGIST_REQUEST;
    memcpy(pdu->caData,strName.toStdString().c_str(), 32);
    memcpy(pdu->caData + 32,strPwd.toStdString().c_str(), 32);
    sendPDU(pdu);
}

void Client::on_login_PB_clicked()
{
    QString strName = ui->user_LE->text();
    QString strPwd = ui->pwd_LE->text();
    m_strLoginName = strName;

    PDU* pdu = mkPDU(0);//括号里是柔性数组的长度
    pdu->uiMsgType = ENUM_MSG_TYPE_LOGIN_REQUEST;
    memcpy(pdu->caData,strName.toStdString().c_str(), 32);
    memcpy(pdu->caData + 32,strPwd.toStdString().c_str(), 32);
    sendPDU(pdu);
}
